﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace xycn.common
{
    /// <summary>
    /// 字符串扩展
    /// </summary>
    public static class StringExtension
    {
        /// <summary>
        /// 判断字符串是否为空
        /// </summary>
        /// <param name="val">要判断得字符串</param>
        /// <returns></returns>
        public static bool IsNullOrEmpty(this string val)
        {
            return string.IsNullOrWhiteSpace(val);
        }

        /// <summary>
        /// JSON序列化
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>JSON字符串</returns>
        public static string ToJsonString(this object obj)
        {
            try
            {
                JsonSerializerOptions options = new(JsonSerializerDefaults.Web)
                {
                    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                    WriteIndented = true
                };
                return JsonSerializer.Serialize(obj, options);
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="json">JSON字符串</param>
        /// <returns>对象</returns>
        public static T DeserializeObject<T>(this string json)
        {
            JsonSerializerOptions options = new(JsonSerializerDefaults.Web)
            {
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                WriteIndented = true
            };
            options.Converters.Add(new DateTimeConverterUsingDateTimeParse());

            return JsonSerializer.Deserialize<T>(json, options);
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="json">JSON字符串</param>
        /// <returns>对象</returns>
        public static T GetModelByJson<T>(this string json)
        {
            return DeserializeObject<T>(json);
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="json">JSON字符串</param>
        /// <returns>对象</returns>
        public static T GetModelByJson<T>(this object json)
        {
            return DeserializeObject<T>(json.ToString());
        }

        /// <summary>
        /// 字符串首字母大写,其余字符全转换为小写
        /// </summary>
        /// <param name="obj">原字符串</param>
        /// <returns>System.String.</returns>
        public static string ToFirstUpper(this string obj)
        {
            if (string.IsNullOrWhiteSpace(obj))
            {
                return obj;
            }
            else if (obj.Length == 1)
            {
                return obj.ToUpper();
            }
            else
            {
                return obj.Substring(0, 1).ToUpper() + obj.Substring(1, obj.Length - 1).ToLower();
            }
        }

        /// <summary>
        /// 字符串首字母大写,其余字符大小写保持不变
        /// </summary>
        /// <param name="obj">原字符串</param>
        /// <returns>System.String.</returns>
        public static string ToOnlyFirstUpper(this string obj)
        {
            if (string.IsNullOrWhiteSpace(obj))
            {
                return obj;
            }
            else if (obj.Length == 1)
            {
                return obj.Trim();
            }
            else
            {
                return obj.Substring(0, 1).ToUpper() + obj.Substring(1, obj.Length - 1).Trim();
            }
        }

        /// <summary>
        /// 字符串首字母小写,其余字符全转换为大写
        /// </summary>
        /// <param name="obj">原字符串</param>
        /// <returns>System.String.</returns>
        public static string ToFirstLower(this string obj)
        {
            if (string.IsNullOrWhiteSpace(obj))
            {
                return obj;
            }
            else if (obj.Length == 1)
            {
                return obj.ToUpper();
            }
            else
            {
                return obj.Substring(0, 1).ToLower() + obj.Substring(1, obj.Length - 1).ToUpper();
            }
        }

        /// <summary>
        /// 字符串首字母小写,其余字符大小写保持不变
        /// </summary>
        /// <param name="obj">原字符串</param>
        /// <returns>System.String.</returns>
        public static string ToOnlyFirstLower(this string obj)
        {
            if (string.IsNullOrWhiteSpace(obj))
            {
                return obj;
            }
            else if (obj.Length == 1)
            {
                return obj.Trim();
            }
            else
            {
                return obj.Substring(0, 1).ToLower() + obj.Substring(1, obj.Length - 1).Trim();
            }
        }


        /// <summary>
        /// 添加空格 添加内容 添加换行
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="spaceNum">The space number.</param>
        /// <param name="msg">The MSG.</param>
        /// <returns>StringBuilder.</returns>
        public static StringBuilder AppendSpaceLine(this StringBuilder obj, int spaceNum, string msg)
        {
            for (int i = 0; i < spaceNum; i++)
            {
                obj.Append("\t");
            }
            obj.Append(msg);
            obj.AppendLine();
            return obj;
        }

        /// <summary>
        /// 添加内容 添加换行
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="msg">The MSG.</param>
        /// <returns>StringBuilder.</returns>
        public static StringBuilder AppendMsgLine(this StringBuilder obj, string msg)
        {
            return obj.AppendSpaceLine(0, msg);
        }

        /// <summary>
        /// 判断一个字符串是否为Null string.Empty "" 等空
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <returns>System.String.</returns>
        public static bool IsNullOrSpace(this string obj)
        {
            if (string.IsNullOrWhiteSpace(obj))
            {
                return true;
            }
            else if (obj.Length == 0)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 判断对象是否为Null string.Empty "" 等空
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <returns>System.String.</returns>
        public static bool IsNullOrSpace(this object obj)
        {
            if (obj == null)
            {
                return true;
            }
            else if (string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return true;
            }
            else if (obj.ToString().Length == 0)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 判断一个字符串是否为Null string.Empty "" 等空
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <returns>System.String.</returns>
        public static bool IsNull(this string obj)
        {
            if (string.IsNullOrWhiteSpace(obj))
            {
                return true;
            }
            else if (obj.Length == 0)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 判断对象是否为Null string.Empty "" 等空
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <returns>System.String.</returns>
        public static bool IsNull(this object obj)
        {
            if (obj == null)
            {
                return true;
            }
            else if (string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return true;
            }
            else if (obj.ToString().Length == 0)
            {
                return true;
            }
            return false;
        }


        /// <summary>
        /// 判断一个字符串是否为Null string.Empty "" 等空
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <returns>System.String.</returns>
        public static bool IsNullOrEmpty(this object obj)
        {
            return IsNull(obj);
        }

        /// <summary>
        /// 处理换行
        /// </summary>
        /// <param name="srcstr">The SRCSTR.</param>
        /// <returns>System.String.</returns>
        public static string RemoverEnter(this string srcstr)
        {
            var enterste = Environment.NewLine;

            return srcstr.Replace(enterste, ",");
        }

        /// <summary>
        /// 将json字符串转换为字典 主要处理时间 value为null 的自动过滤
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static Dictionary<string, object> ToDictionary(this string json)
        {
            var dic = JsonSerializer.Deserialize<Dictionary<string, object>>(json);

            var allkeys = dic.Keys.ToList();

            foreach (var item in allkeys)
            {
                if (dic[item] == null)
                {
                    dic.Remove(item);
                    continue;
                }
                if (dic[item].GetType() == typeof(DateTime))
                {
                    dic[item] = Convert.ToDateTime(dic[item]).ToString("yyyy-MM-dd HH:mm:ss");
                }
            }
            return dic;
        }

        /// <summary>
        /// 将json字符串转换为字典 处理时间和Key转小写 value=null 自动过滤
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static Dictionary<string, object> ToDictionaryWithKeyToLower(this string json)
        {
            var dic = ToDictionary(json.ToString());
            var retdic = new Dictionary<string, object>();
            foreach (var item in dic)
            {
                if (retdic.ContainsKey(item.Key.ToLower()) == false && item.Value != null)
                    retdic.Add(item.Key.ToLower(), item.Value);
            }

            return retdic;
        }


        /// <summary>
        /// 将json字符串转换为字典 主要处理时间
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static List<Dictionary<string, object>> ToDictionaryList(this string json)
        {
            var diclst = JsonSerializer.Deserialize<List<Dictionary<string, object>>>(json);

            for (int i = 0; i < diclst.Count; i++)
            {
                var allkeys = diclst[i].Keys.ToList();

                foreach (var item in allkeys)
                {
                    if (diclst[i][item].IsNull() == false && diclst[i][item].GetType() == typeof(DateTime))
                    {
                        diclst[i][item] = Convert.ToDateTime(diclst[i][item]).ToString("yyyy-MM-dd HH:mm:ss");
                    }
                }
            }
            return diclst;
        }

        /// <summary>
        /// 将json字符串转换为字典 主要处理时间
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static Dictionary<string, object> ToDictionary(this object json)
        {
            return ToDictionary(json.ToString());
        }

        /// <summary>
        /// 将json字符串转换为字典 处理时间和Key转小写  value=null 自动过滤
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static Dictionary<string, object> ToDictionaryWithKeyToLower(this object json)
        {
            var dic = ToDictionary(json.ToString());
            var retdic = new Dictionary<string, object>();
            foreach (var item in dic)
            {
                if (retdic.ContainsKey(item.Key.ToLower()) == false && item.Value != null)
                    retdic.Add(item.Key.ToLower(), item.Value);
            }

            return retdic;
        }

        /// <summary>
        /// 将json字符串转换为字典 主要处理时间
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static List<Dictionary<string, object>> ToDictionaryList(this object json)
        {
            return ToDictionaryList(json.ToString());
        }
        
        /// <summary>
        /// 将json字符串转换为字典 主要处理时间 处理成 to_date('" + lasttime.Value.ToMyString() + "','YYYY-MM-DD HH24:MI:SS')
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static List<Dictionary<string, object>> ToDictionaryListByOracleDB(this object json)
        {
            return ToDictionaryListByOracleDB(json.ToString());
        }

        /// <summary>
        /// 获取一个字符串 前后字符串之间的串 如  abcdefg 获取 b f  之间的,即为 cde 不包含开始字符
        /// 如果首字符不存在 则从0开始 如果尾字符不存在则取最大值
        /// </summary>
        /// <param name="srcstr">原始字符串 "" 表示开始字符 不支持null</param>
        /// <param name="startChar">开始匹配字符串 "" 表示结束字符 不支持null</param>
        /// <param name="endChar">结束匹配字符串</param>
        /// <param name="inStartChar">结果是否包含开始字符 默认不包含</param>
        /// <param name="inEndChar">结果是否包含结束字符 默认不包含</param>
        /// <returns></returns>
        public static string GetBetweenChar(this string srcstr, string startChar, string endChar, bool inStartChar = false, bool inEndChar = false)
        {
            if (srcstr.IsNull())
            {
                return "";
            }

            var bid = srcstr.IndexOf(startChar);
            if (startChar == "" || bid == -1)
            {
                bid = 0;
            }
            else if (inStartChar == false)
            {
                bid += startChar.Length;
            }
            var eid = srcstr.IndexOf(endChar);
            if (endChar == "" || eid == -1)
            {
                eid = srcstr.Length;
            }
            else if (inEndChar)
            {
                eid += endChar.Length;
            }

            if (eid <= bid)
            {
                return "";
            }
            return srcstr.Substring(bid, eid - bid);
        }
    }

    /// <summary>
    /// json日期时间处理
    /// </summary>
    public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="typeToConvert"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return DateTime.Parse(reader.GetString());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="value"></param>
        /// <param name="options"></param>
        public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
        }
    }
}
